/**
  **************************************************************************
  * @file     main.c
  * @version  v2.0.6
  * @date     2022-05-20
  * @brief    main program
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to
  * download from Artery official website is the copyrighted work of Artery.
  * Artery authorizes customers to use, copy, and distribute the BSP
  * software and its related documentation for the purpose of design and
  * development in conjunction with Artery microcontrollers. Use of the
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */

#include "at32f421_board.h"
#include "at32f421_clock.h"

/** @addtogroup AT32F421_periph_template
  * @{
  */

/** @addtogroup 421_LED_toggle LED_toggle
  * @{
  */

#define DELAY                            100
#define FAST                             1
#define SLOW                             4

uint8_t g_speed = FAST;

void button_exint_init(void);
void button_isr(void);

/**
  * @brief  configure button exint
  * @param  none
  * @retval none
  */
void button_exint_init(void)
{
  exint_init_type exint_init_struct;

  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);

  scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOA, SCFG_PINS_SOURCE0);

  exint_default_para_init(&exint_init_struct);
  exint_init_struct.line_enable = TRUE;
  exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
  exint_init_struct.line_select = EXINT_LINE_0;
  exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  exint_init(&exint_init_struct);

  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(EXINT1_0_IRQn, 0, 0);
}

/**
  * @brief  button handler function
  * @param  none
  * @retval none
  */
void button_isr(void)
{
  /* delay 5ms */
  delay_ms(5);

  /* clear interrupt pending bit */
  exint_flag_clear(EXINT_LINE_0);

  /* check input pin state */
  if(SET == gpio_input_data_bit_read(USER_BUTTON_PORT, USER_BUTTON_PIN))
  {
    if(g_speed == SLOW)
      g_speed = FAST;
    else
      g_speed = SLOW;
  }
}

/**
  * @brief  exint0 interrupt handler
  * @param  none
  * @retval none
  */
void EXINT1_0_IRQHandler(void)
{
  button_isr();
}

static void init_gpio(gpio_type *gpio_baseABCD,uint32_t pins,gpio_mode_type typ){
  gpio_init_type gpio_init_struct;

  /* enable the led clock */
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

  /* set default parameter */
  gpio_default_para_init(&gpio_init_struct);

  /* configure the led gpio */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = typ;
  gpio_init_struct.gpio_pins = pins;
  gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
  gpio_init(gpio_baseABCD, &gpio_init_struct);
}

const uint16_t PIN_S[16] = {
		GPIO_PINS_0 ,
		GPIO_PINS_1 ,
		GPIO_PINS_2 ,
		GPIO_PINS_3 ,
		GPIO_PINS_4 ,
		GPIO_PINS_5 ,
		GPIO_PINS_6 ,
		GPIO_PINS_7 ,
		GPIO_PINS_8 ,
		GPIO_PINS_9 ,
		GPIO_PINS_10,
		GPIO_PINS_11,
		GPIO_PINS_12,
		GPIO_PINS_13,
		GPIO_PINS_14,
		GPIO_PINS_15,
};

#define DATA_OUT_PIN 15
#define DATA_IN_PIN  14
#define DATA_CLK_PIN 13
#define DATA_DIR_PIN 12
#define DATA_CS_PIN  11
#define CPU_RUN_PIN	 10

gpio_type* gpioptr = 0;
static fpga_init_pin(){
	gpioptr = GPIOB;
	init_gpio(GPIOB,PIN_S[DATA_OUT_PIN],GPIO_MODE_OUTPUT);
	init_gpio(GPIOB,PIN_S[ DATA_IN_PIN], GPIO_MODE_INPUT);
	init_gpio(GPIOB,PIN_S[DATA_CLK_PIN],GPIO_MODE_OUTPUT);
	init_gpio(GPIOB,PIN_S[DATA_DIR_PIN],GPIO_MODE_OUTPUT);
	init_gpio(GPIOB,PIN_S[ DATA_CS_PIN],GPIO_MODE_OUTPUT);
	init_gpio(GPIOB,PIN_S[ CPU_RUN_PIN],GPIO_MODE_OUTPUT);
}

#define PIN_SET(pin) 	(1<<pin)
#define PIN_CLR(pin) 	((1<<pin)<<16)
#define PIN_DAT(pin,v)  \
		(PIN_CLR(pin)| \
			(((v)&1)<<pin) \
			)


#define DATA_SET(v) 	gpioptr->scr = PIN_DAT(DATA_OUT_PIN,v)
#define DATA_GET()  	((gpioptr->idt>>DATA_IN_PIN)&1)

#define DATA_CLK_SET	gpioptr->scr = PIN_SET(DATA_CLK_PIN)
#define DATA_CLK_CLR	gpioptr->scr = PIN_CLR(DATA_CLK_PIN)

#define DATA_SET_OUT	gpioptr->scr = PIN_SET(DATA_DIR_PIN)
#define DATA_SET_IN 	gpioptr->scr = PIN_CLR(DATA_DIR_PIN)

#define DATA_CS_SET		gpioptr->scr = PIN_CLR(DATA_CS_PIN)
#define DATA_CS_CLR		gpioptr->scr = PIN_SET(DATA_CS_PIN)

#define CPU_RUN_SET		gpioptr->scr = PIN_SET(CPU_RUN_PIN)
#define CPU_RUN_CLR		gpioptr->scr = PIN_CLR(CPU_RUN_PIN)

#define CPU_RUN_CYCYLE1 DATA_CLK_SET;DATA_CLK_CLR;

static int fpga_write32(u32 value){
	int pos = 0;
	for(pos=0;pos<32;pos++){
		DATA_CLK_CLR;
		DATA_SET(value);
		DATA_CLK_SET;
		value >>= 1;
	}
	return 0;
}

static int fpga_read32(){
	u32 dat = 0;
	int i = 0;
	for(i=0;i<32;i++){
		DATA_CLK_SET;
		DATA_CLK_CLR;
		dat |= DATA_GET() << i;
	}
	return dat;
}

static int fpga_write(u32*buf,int size){
	int i = 0;
	DATA_CS_CLR;
	DATA_CLK_CLR;
	DATA_SET_OUT;

	DATA_CS_SET;		//开启传输
	for(i=0;i<size;i++){
		fpga_write32(buf[i]);
	}
	DATA_CS_CLR;		//开闭传输
	return 0;
}

static int fpga_read(u32*buf,int size){
	int i = 0;
	DATA_CS_CLR;	//初始化
	DATA_CLK_CLR;	//CLK为低
	DATA_SET_IN;	//设置为输入
	DATA_CS_SET;		//开启传输
	for(i=0;i<size;i++){
		buf[i] = fpga_read32();
	}
	DATA_CS_CLR;		//开闭传输
	return 0;
}

/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
  system_clock_config();
  u32 sram[100];
  int i = 0;
  for(i=0;i<64;i++){
	  sram[i] = 0x12345600+i;
  }
  sram[0] = 4;

  //初始化
  //while(1){};
  fpga_init_pin();
  //fpga_write(sram,64);
  CPU_RUN_CLR;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;

  DATA_CS_CLR;
  CPU_RUN_SET;
  //mv
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  //addi
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;

  //sw
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;


  do{
	  CPU_RUN_CYCYLE1;
  }while(1);

  //addi
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;


  //sw
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;

  //mv
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  CPU_RUN_CYCYLE1;
  if(0){

	  //mv
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;

	  //bne
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  //sw
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;


	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;

	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;

	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1; //a = 2
	  CPU_RUN_CYCYLE1; //a = 3

	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;

	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;

	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1; //a = 3
	  CPU_RUN_CYCYLE1; //a = 4

	  //bne
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;

	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
	  CPU_RUN_CYCYLE1;
}
  while(0){
	  CPU_RUN_CYCYLE1;
  };

  CPU_RUN_CLR;

  DATA_CS_CLR;
  DATA_CLK_CLR;
  DATA_CLK_SET;
  DATA_CLK_CLR;
  DATA_CLK_SET;
  fpga_read(sram,99);
  while(1){
  };

  //at32_board_init();

  button_exint_init();

  while(1)
  {
    at32_led_toggle(LED2);
    delay_ms(g_speed * DELAY);
    at32_led_toggle(LED3);
    delay_ms(g_speed * DELAY);
    at32_led_toggle(LED4);
    delay_ms(g_speed * DELAY);
  }
}

/**
  * @}
  */

/**
  * @}
  */
